use std::fs;

use bindgen::Builder;
use cc::Build;

#[cfg(feature = "cm3")]
fn add_cm3(cc: &mut Build) {
    cc.include("./device_stm32f103");
    cc.file("./c_src/device_stm32f103/system_stm32f10x.c");
    cc.define("CM3", "");
    cc.define("STM32F10X_HD", "");
}

#[cfg(any(feature = "cm4", feature = "cm4_25"))]
fn add_cm4(cc: &mut Build) {
    #[cfg(feature = "cm4")]
    cc.file("./c_src/device_stm32f4/system_stm32f4xx.c");

    #[cfg(feature = "cm4_25")]
    cc.file("./c_src/device_stm32f4/system_stm32f4xx_25.c");

    cc.include("./device_stm32f4");
    cc.define("CM4", "");
    cc.define("STM32F40_41xxx", "");
}

fn add_rtos_c(cc: &mut Build) {
    const RTOS_DIR: &'static str = "./c_src";

    let mut dir = fs::read_dir(RTOS_DIR).unwrap();
    while let Some(Ok(file)) = dir.next() {
        let file_type = if let Ok(file_type) = file.file_type() {
            file_type
        } else {
            continue
        };
        if !file_type.is_file() {
            continue;
        }
        let name = file.file_name();
        let name = name.to_str().unwrap_or("");
        if !name.ends_with(".c") {
            continue;
        }
        let path = format!("{}/{}", RTOS_DIR, name);
        cc.file(path);
    }
    #[cfg(any(feature = "cm3", feature = "cm4", feature = "cm4_25"))]
    let asm = format!("{}/gcc/irq_armv7m.S", RTOS_DIR);

    #[cfg(feature = "cm0")]
    let asm = format!("{}/gcc/irq_armv6m.S", RTOS_DIR);

    cc.file(asm);
}



fn build_lib() {
    let mut cc = Build::new();
    cc.include("./c_src/CMSIS");
    cc.include("./c_src");
    
    #[cfg(feature = "cm3")]
    add_cm3(&mut cc);

    #[cfg(any(feature = "cm4", feature = "cm4_25"))]
    add_cm4(&mut cc);

    add_rtos_c(&mut cc);
    cc.try_compile("cmsis_rtos2").unwrap();
}

fn bind_header(path: &str, rs: &str) {
    Builder::default()
        .use_core()
        .header(path)
        .generate().unwrap()
        .write_to_file(rs).unwrap();
}

fn bind_inc() {
    bind_header("./c_src/rtx_os.h", "./rtx_os.rs");

    #[cfg(feature = "cm3")]
    bind_header("./c_src/device_stm32f103/system_stm32f10x.h", "./system_stm32f10x.rs");

    #[cfg(any(feature = "cm4", feature = "cm4_25"))]
    bind_header("./c_src/device_stm32f4/system_stm32f4xx.h", "./system_stm32f4xx.rs");
}

fn main() {
    build_lib();
    bind_inc();
}
